package com.tengju.bff.interfaces.manage.crm.user.assembler;

import com.tengju.bff.interfaces.manage.crm.user.vo.*;
import com.tengju.bff.interfaces.shared.MobileVO;
import com.tengju.user.application.user.dto.UserSearchForm;
import com.tengju.user.domain.model.doc.UserDocument;
import com.tengju.user.domain.model.club.Club;
import com.tengju.user.domain.model.club.ClubId;
import com.tengju.user.domain.model.sign.*;
import com.tengju.user.domain.model.star.StarIndicator;
import com.tengju.user.domain.model.star.StarIndicatorType;
import com.tengju.user.domain.model.user.StarLevelEnum;
import com.tengju.user.domain.model.user.UserDetail;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;


public class UserAssembler {

    public static UserDetailVO modelToVo(UserDetail userDetail, Club club, UserInfo clubFounder, UserInfo parentUserInfo, List<UserInfo> leaderUserInfos, StarSignInfo signInfo, LocalDateTime upgradeTime) {

        Integer starLevel = Optional.ofNullable(signInfo).map(StarSignInfo::getStarLevel).orElse(null);
        StarLevelEnum starLevelEnum = StarLevelEnum.parseByCode(starLevel);

        StarSignStepEnum step = StarSignStepEnum.getByStep(Optional.ofNullable(signInfo).map(StarSignInfo::getStep).orElse(null));
        StarAuditStatEnum auditStat = StarAuditStatEnum.fromVal(Optional.ofNullable(signInfo).map(StarSignInfo::getAuditStat).orElse(null));
        StarSignStatus starSignStatus = StarSignStatus.fromStepAndAuditStat(step, auditStat);

        String signStat = "";
        if (starLevelEnum != null && starSignStatus != null) {
            signStat = starSignStatus.getDesc() + "(" + starLevelEnum.getDesc() + ")";
        }

        String createTime = Optional.ofNullable(userDetail.getCreateTime())
                .map(time -> time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .orElse(null);

        Map<UserIdCode, UserInfo> leaderUserMap = leaderUserInfos.stream().collect(Collectors.toMap(UserInfo::getIdCode, Function.identity()));

        UserInfo belongEc = leaderUserMap.get(userDetail.getBelongEc());
        UserInfo belongSec = leaderUserMap.get(userDetail.getBelongSec());
        UserInfo belongEec = leaderUserMap.get(userDetail.getBelongEec());

        if (userDetail.getStarLevel() == StarLevelEnum.NONE) {
            upgradeTime = userDetail.getUpgradeBlackCardTime();
        }

        String upgradeTimeStr = Optional.ofNullable(upgradeTime)
                .map(time -> time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
                .orElse("") + "(" + userDetail.getStarLevel().getDesc() + ")";


        return new UserDetailVO(userDetail.getIdCode().getValue(),
                new MobileVO(userDetail.wholePhoneNumber()),
                userDetail.getStarLevel().getDesc(),
                userDetail.getName(),
                new NicknameVO(userDetail.getNickname(),userDetail.wholePhoneNumber()),
                signStat,createTime,Optional.ofNullable(parentUserInfo).map(UserInfo::getName).orElse(""),
                new NicknameVO(Optional.ofNullable(parentUserInfo).map(UserInfo::getNickName).orElse(null),
                        Optional.ofNullable(parentUserInfo).map(UserInfo::getWholePhoneNumber).orElse(null)),
                new MobileVO(Optional.ofNullable(parentUserInfo).map(UserInfo::getMobile).orElse(null)),
                Optional.ofNullable(parentUserInfo).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                Optional.ofNullable(parentUserInfo).map(UserInfo::getStarLevel).map(StarLevelEnum::parseByCode).map(StarLevelEnum::getDesc).orElse(""),
                Optional.ofNullable(club).map(Club::getClubName).orElse(""),
                Optional.ofNullable(clubFounder).map(UserInfo::getNickName).orElse(""),
                Optional.ofNullable(clubFounder).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                Optional.ofNullable(belongEc).map(UserInfo::getNickName).orElse(""),
                Optional.ofNullable(belongEc).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                Optional.ofNullable(belongSec).map(UserInfo::getNickName).orElse(""),
                Optional.ofNullable(belongSec).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                Optional.ofNullable(belongEec).map(UserInfo::getNickName).orElse(""),
                Optional.ofNullable(belongEec).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                upgradeTimeStr);


    }


    public static StarIndicatorVO modelToVo(List<StarIndicator> starIndicatorList) {

        Map<StarIndicatorType, StarIndicator> starIndicatorMap = starIndicatorList.stream()
                .collect(Collectors.toMap(
                        StarIndicator::getStarIndicatorType,
                        Function.identity(),
                        (v1,v2) -> v1
                ));

        return new StarIndicatorVO(
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.DEVELOP_DEALER_NUM))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::intValue).orElse(0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.CUSTOMER_MEMBERS_NUM))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::intValue).orElse(0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.DEVELOP_CITY_SERVICE_NUM))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::intValue).orElse(0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.MANAGE_DEALER_NUM))
                .map(StarIndicator::getIndicatorValue).map(BigDecimal::intValue).orElse(0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.DEVELOP_SEC_NUM))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::intValue).orElse(0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.RECENT_AVG_PROFIT))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::doubleValue).orElse(0.0),
                Optional.ofNullable(starIndicatorMap.get(StarIndicatorType.RECENT_TWO_MONTHS_AVG_ACHIEVEMENT))
                        .map(StarIndicator::getIndicatorValue).map(BigDecimal::doubleValue).orElse(0.0));


    }

    public static UserSearchForm toSearchForm(UserForm form,List<UserIdCode> genSecIdCodes) {

        UserSearchForm searchForm = new UserSearchForm();
        searchForm.setPageIndex(form.getPageIndex());
        searchForm.setPageSize(form.getPageSize());
        searchForm.setMobile(form.getMobile());
        searchForm.setNickname(form.getNickname());
        searchForm.setStarLevel(StarLevelEnum.parseByCode(form.getStarLevel()));
        searchForm.setSignStatusList(CrmStarSignStatus.parse(form.getSignStatus()));


        if (form.getIdCode() != null && form.getIdCode() > 0) {
            UserIdCode idCode = new UserIdCode(form.getIdCode());
            searchForm.setIdCode(idCode);
        }

        if (form.getPidCode() != null && form.getPidCode() > 0) {
            UserIdCode pidCode = new UserIdCode(form.getPidCode());
            searchForm.setPidCode(pidCode);
        }

        if (form.getDominationTeamPidCode() != null && form.getDominationTeamPidCode() > 0) {
            UserIdCode dominationTeamPidCode = new UserIdCode(form.getDominationTeamPidCode());
            searchForm.setDominationTeamPidCode(dominationTeamPidCode);
        }

        searchForm.setSentimentContext(form.getSentimentContext());


        if (form.getSignTargetStarLevel() != null && form.getSignTargetStarLevel() > 0) {
            StarLevelEnum signTargetStarLevel = StarLevelEnum.parseByCode(form.getSignTargetStarLevel());
            searchForm.setSignTargetStarLevel(signTargetStarLevel);
        }

        StarLevelEnum targetStarLevel = StarLevelEnum.parseByCode(form.getUpcomingLevel());
        if (StarLevelEnum.NONE == targetStarLevel) {
            targetStarLevel = null;
        }
        searchForm.setTargetStarLevel(targetStarLevel);

        if (form.getClubId() != null && form.getClubId() > 0) {
            ClubId clubId = new ClubId(form.getClubId());
            List<ClubId> clubIds = List.of(clubId);
            searchForm.setClubIds(clubIds);
        }

        List<Long> genSecIdCodesVal = genSecIdCodes.stream().map(UserIdCode::getValue).collect(Collectors.toList());
        searchForm.setOwnerGenSecIdCodes(genSecIdCodesVal);

        searchForm.setOperator(form.getOperator());
        return searchForm;
    }

    public static UserVo docToVo(UserDocument userDocument, Map<UserIdCode, UserInfo> parentUserMap, Map<UserIdCode, List<StarIndicator>> idCodeStarIndicatorMap) {

        if (userDocument == null) {
            return null;
        }

        UserInfo parentUserInfo = null;
        if (userDocument.getParentIdCode() != null && userDocument.getParentIdCode() > 0) {
            parentUserInfo = parentUserMap.get(new UserIdCode(userDocument.getParentIdCode()));
        }
        String nickname = new NicknameVO(userDocument.getNickName(), userDocument.getMobile()).toString();
        StarLevelEnum targetStarLevel = StarLevelEnum.parseByCode(userDocument.getTargetStarLevel());

        String targetStarLevelStr = "";
        if (targetStarLevel != null && StarLevelEnum.NONE != targetStarLevel) {
            targetStarLevelStr = "即将晋升" + targetStarLevel.getShortName();
        }

        String registerTimeStr = "";
        if (userDocument.getRegisterTime() != null && userDocument.getRegisterTime() > 0) {
            LocalDateTime registerTime = LocalDateTime
                    .ofInstant(Instant.ofEpochMilli(userDocument.getRegisterTime()),ZoneId.systemDefault());
            registerTimeStr = registerTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }

        String starRiseTimeStr = "";
        if (userDocument.getStarRiseTime() != null && userDocument.getStarRiseTime() > 0) {
            LocalDateTime starRiseTime = LocalDateTime
                    .ofInstant(Instant.ofEpochMilli(userDocument.getStarRiseTime()),ZoneId.systemDefault());
            starRiseTimeStr = starRiseTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }

        List<StarIndicatorColumnVO> notSatisfiedIndicators = Collections.emptyList();
        if (userDocument.getIdCode() != null && idCodeStarIndicatorMap.containsKey(UserIdCode.of(userDocument.getIdCode()))) {
            List<StarIndicator> starIndicators = idCodeStarIndicatorMap.get(UserIdCode.of(userDocument.getIdCode()));
            notSatisfiedIndicators = starIndicators.stream()
                    .map(UserAssembler::toIndicatorVO)
                    .collect(Collectors.toList());

        }


        return new UserVo(userDocument.getIdCode(),
                new MobileVO(userDocument.getMobile()),
                userDocument.getName(),
                userDocument.getStarLevel(),
                Optional.ofNullable(parentUserInfo).map(UserInfo::getIdCode).map(UserIdCode::getValue).orElse(null),
                Optional.ofNullable(parentUserInfo).map(UserInfo::getName).orElse(""),
                userDocument.getStarSignStatus(),
                Optional.ofNullable(StarLevelEnum.parseByCode(userDocument.getStarLevel()))
                        .map(StarLevelEnum::getShortName).orElse(""),
                Optional.ofNullable(StarLevelEnum.parseByCode(userDocument.getSignTargetStarLevel()))
                        .map(StarLevelEnum::getShortName).orElse(""),
                nickname,
                targetStarLevelStr,
                notSatisfiedIndicators,
                registerTimeStr,
                starRiseTimeStr);


    }

    private static StarIndicatorColumnVO toIndicatorVO(StarIndicator starIndicator) {
        if (starIndicator == null) {
            return null;
        }
        BigDecimal indicatorDiff = starIndicator.getIndicatorTargetValue().subtract(starIndicator.getIndicatorValue());
        return new StarIndicatorColumnVO(
                starIndicator.getStarIndicatorType(),
                starIndicator.getIndicatorValue(),
                starIndicator.getIndicatorTargetValue(),
                indicatorDiff,
                starIndicator.getIndicatorDay(),
                starIndicator.getStarIndicatorType().getDesc() + " 还差 " + indicatorDiff.intValue()
        );
    }


}
